<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
	<meta name="keywords" content="nacos" />
	<meta name="description" content="Nacos 配置管理帮我们解决什么问题？" />
	<!-- 网页标签标题 -->
	<title>Nacos 帮我们解决什么问题？—— 配置管理篇</title>
	<link rel="shortcut icon" href="https://img.alicdn.com/tfs/TB1hgJpHAPoK1RjSZKbXXX1IXXa-64-64.png"/>
	<link rel="stylesheet" href="/build/blogDetail.css" />
</head>
<body>
	<div id="root"><div class="blog-detail-page" data-reactroot="" data-reactid="1" data-react-checksum="1072454089"><header class="header-container header-container-normal" data-reactid="2"><div class="header-body" data-reactid="3"><a href="/en-us/index.html" data-reactid="4"><img class="logo" src="/img/nacos_colorful.png" data-reactid="5"/></a><div class="search search-normal" data-reactid="6"><span class="icon-search" data-reactid="7"></span></div><span class="language-switch language-switch-normal" data-reactid="8">中</span><div class="header-menu" data-reactid="9"><img class="header-menu-toggle" src="/img/menu_gray.png" data-reactid="10"/><ul data-reactid="11"><li class="menu-item menu-item-normal" data-reactid="12"><a href="/en-us/index.html" data-reactid="13">HOME</a></li><li class="menu-item menu-item-normal" data-reactid="14"><a href="/en-us/docs/quick-start.html" data-reactid="15">DOCS</a></li><li class="menu-item menu-item-normal menu-item-normal-active" data-reactid="16"><a href="/en-us/blog" data-reactid="17">BLOG</a></li><li class="menu-item menu-item-normal" data-reactid="18"><a href="/en-us/community" data-reactid="19">COMMUNITY</a></li><li class="menu-item menu-item-normal" data-reactid="20"><a href="https://cn.aliyun.com/product/aliware/mse?spm=nacos-website.topbar.0.0.0" data-reactid="21">NACOS IN CLOUD</a><img class="menu-img" src="https://img.alicdn.com/tfs/TB1esl_m.T1gK0jSZFrXXcNCXXa-200-200.png" data-reactid="22"/></li><li class="menu-item menu-item-normal" data-reactid="23"><a href="https://job.alibaba.com/zhaopin/position_detail.htm?trace=qrcode_share&amp;positionCode=GP633620" data-reactid="24">HIRING</a><img class="menu-img" src="https://img.alicdn.com/tfs/TB1esl_m.T1gK0jSZFrXXcNCXXa-200-200.png" data-reactid="25"/></li><li class="menu-item menu-item-normal" data-reactid="26"><a href="http://console.nacos.io/nacos/index.html" data-reactid="27">DEMO-CONSOLE</a></li></ul></div></div></header><section class="blog-content markdown-body" data-reactid="28"><h1>Nacos 帮我们解决什么问题？—— 配置管理篇</h1>
<blockquote>
<p>Authors: 何煦</p>
</blockquote>
<h2>概述</h2>
<p><a href="https://github.com/alibaba/nacos">Nacos</a> 是阿里巴巴今年7月份开源的项目，如其名， Naming and Configuration Service ，专注于服务发现和配置管理领域。本系列文章，将从 5W1H（What、Where、When、Who、Why、How）全面剖析 Nacos，希望对开发者们在服务发现和配置管理开源方案选型的时候，有所帮助。</p>
<p>本文作为 Nacos 系列文章的开篇，从 “What” 开始。我们开始关注一个开源项目的时候，通常最先冒出的 2 个问题是：</p>
<ul>
<li>它是什么？</li>
<li>它帮我们解决什么问题？</li>
</ul>
<p>Nacos 是什么？</p>
<p>Nacos 是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。</p>
<p>Nacos 能帮我们解决什么问题？</p>
<p>本文将先围绕其“配置管理”功能来解答。配置，作为代码如影随形的小伙伴，伴随着应用的整个生命周期，我们当然对它也非常的熟悉，想想配置一般都通过哪几种形式存在？</p>
<ul>
<li>硬编码</li>
<li>配置文件</li>
<li>DB 配置表</li>
</ul>
<h2>硬编码</h2>
<p>配置项作为类字段的形式存在，如：</p>
<pre><code class="language-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppConfig</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> connectTimeoutInMills = <span class="hljs-number">5000</span>;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getConnectTimeoutInMills</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> connectTimeoutInMills;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setConnectTimeoutInMills</span><span class="hljs-params">(<span class="hljs-keyword">int</span> connectTimeoutInMills)</span> </span>{
        <span class="hljs-keyword">this</span>.connectTimeoutInMills = connectTimeoutInMills;
    }
}
</code></pre>
<p>这种形式主要有三个问题：</p>
<p>如果配置是需要动态修改的话，需要当前应用去暴露管理该配置项的接口，至于是 Controller 的 API 接口，还是 JMX ，都是可以做到。</p>
<p>另外，配置变更都是发生在内存中，并没有持久化。因此，在修改配置之后重启应用，配置又会变回代码中的默认值了，这是一个坑啊，笔者就曾经掉进去过，爬了好一会才上岸。</p>
<p>最后一个问题，就是当你有多台机器的时候，要修改一个配置，每一台都得去操作一遍，运维成本可想而知，极其蛋疼。</p>
<h2>配置文件</h2>
<p>Spring 中常见的 properties、yml 文件，或其他自定义的，如，“conf”后缀等：</p>
<pre><code># application.properties
connectTimeoutInMills=5000
</code></pre>
<p>相比“硬编码”的形式，它解决了第二个问题，持久化了配置。但是，另外两个问题并没有解决，运维成本依旧还是很高的。</p>
<p>配置动态变更，可以是通过类似“硬编码”暴露管理接口的方式，这时，代码中会多一步持久化新配置到文件的逻辑。或者，简单粗暴点，直接登录机器上去修改配置文件，再重启应用，让配置生效。当然，你也可以在代码中增加一个定时任务，如每隔 10s 读取配置文件内容，让最新的配置能够及时在应用中生效，这样也就免去了重启应用这个“较重”的运维操作。</p>
<p>通过增加“持久化逻辑”、“定时任务”让“配置文件”的形式比“硬编码”前进了一小步。</p>
<h2>DB 配置表</h2>
<p>这里的 DB 可以是 MySQL 等的关系型数据库，也可以是 Redis 等的非关系型数据库。数据表如：</p>
<pre><code class="language-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-string">`config`</span> (
  <span class="hljs-string">`id`</span> <span class="hljs-built_in">bigint</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span> AUTO_INCREMENT,
  <span class="hljs-string">`key`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">50</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-string">''</span> <span class="hljs-keyword">COMMENT</span> <span class="hljs-string">'配置项'</span>,
  <span class="hljs-string">`value`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">50</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-string">''</span> <span class="hljs-keyword">COMMENT</span> <span class="hljs-string">'配置内容'</span>,
  <span class="hljs-string">`updated_time`</span> <span class="hljs-keyword">timestamp</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CURRENT_TIMESTAMP</span> <span class="hljs-keyword">ON</span> <span class="hljs-keyword">UPDATE</span> <span class="hljs-keyword">CURRENT_TIMESTAMP</span>,
  <span class="hljs-string">`created_time`</span> <span class="hljs-keyword">timestamp</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CURRENT_TIMESTAMP</span>,
  PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`id`</span>),
  <span class="hljs-keyword">UNIQUE</span> <span class="hljs-keyword">KEY</span> <span class="hljs-string">`idx_key`</span> (<span class="hljs-string">`key`</span>)
) <span class="hljs-keyword">ENGINE</span>=<span class="hljs-keyword">InnoDB</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8 <span class="hljs-keyword">COMMENT</span>=<span class="hljs-string">'配置信息'</span>;

<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> <span class="hljs-string">`config`</span> (<span class="hljs-string">`key`</span>, <span class="hljs-string">`value`</span>, <span class="hljs-string">`updated_time`</span>, <span class="hljs-string">`created_time`</span>) <span class="hljs-keyword">VALUES</span> (<span class="hljs-string">'connectTimeoutInMills'</span>, <span class="hljs-string">'5000'</span>, <span class="hljs-keyword">CURRENT_TIMESTAMP</span>, <span class="hljs-keyword">CURRENT_TIMESTAMP</span>);
</code></pre>
<p>它相对于前两者，更进一步，将配置从应用中抽离出来，集中管理，能较大的降低运维成本。</p>
<p>那么，它能怎么解决动态更新配置的问题呢？据我所知，有两种方式。</p>
<p>其一，如同之前一样，通过暴露管理接口去解决，当然，也一样得增加持久化的逻辑，只不过，之前是写文件，现在是将最新配置写入数据库。不过，程序中还需要有定时从数据库读取最新配置的任务，这样，才能做到只需调用其中一台机器的管理配置接口，就能把最新的配置下发到整个应用集群所有的机器上，真正达到降低运维成本的目的。</p>
<p>其二，直接修改数据库，程序中通过定时任务从数据库读取最新的配置内容。</p>
<p>“DB 配置表”的形式解决了主要的问题，但是它不够优雅，带来了一些“累赘”。</p>
<h2>Nacos 配置管理</h2>
<p>Nacos 真正将配置从应用中剥离出来，统一管理，优雅的解决了配置的动态变更、持久化、运维成本等问题。</p>
<p>应用自身既不需要去添加管理配置接口，也不需要自己去实现配置的持久化，更不需要引入“定时任务”以便降低运维成本。Nacos 提供的配置管理功能，将配置相关的所有逻辑都收拢，并且提供简单易用的 SDK，让应用的配置可以非常方便被 Nacos 管理起来。</p>
<p>如果是在 Spring 中使用 Nacos，只需三个步骤即可：</p>
<ol>
<li>添加依赖</li>
</ol>
<pre><code class="language-plain">&lt;dependency&gt;
    &lt;groupId&gt;com.alibaba.nacos&lt;/groupId&gt;
    &lt;artifactId&gt;nacos-spring-context&lt;/artifactId&gt;
    &lt;version&gt;${latest.version}&lt;/version&gt;
&lt;/dependency&gt;
</code></pre>
<ol start="2">
<li>添加 <code>@EnableNacosConfig</code> 注解启用 Nacos Spring 的配置管理服务。以下示例中，我们使用 <code>@NacosPropertySource</code> 加载了 <code>dataId</code> 为 <code>example</code> 的配置源，并开启自动更新：</li>
</ol>
<pre><code class="language-plain">@Configuration
@EnableNacosConfig(globalProperties = @NacosProperties(serverAddr = &quot;127.0.0.1:8848&quot;))
@NacosPropertySource(dataId = &quot;example&quot;, autoRefreshed = true)
public class NacosConfiguration {

}
</code></pre>
<ol start="3">
<li>通过 Spring 的 <code>@Value</code> 注解设置属性值。</li>
</ol>
<p>注意：需要同时有 <code>Setter</code>方法才能在配置变更的时候自动更新。</p>
<pre><code class="language-plain">public class AppConfig {

    @Value(&quot;${connectTimeoutInMills:5000}&quot;)
    private int connectTimeoutInMills;

    public int getConnectTimeoutInMills() {
        return connectTimeoutInMills;
    }

    public void setConnectTimeoutInMills(int connectTimeoutInMills) {
        this.connectTimeoutInMills = connectTimeoutInMills;
    }
}
</code></pre>
<p>以上的三个步骤，对应用本身几乎没有任何的侵入，1 个依赖 2 注解，寥寥数行，就把配置通过 Nacos 管理起来了。</p>
<p>关于配置的动态更新，对 Nacos Spring 的用户来说，在自身应用中就只是设置 “autoRefreshed” 的一个布尔值。然后在需要修改配置的时候，调用 Nacos 修改配置的接口，或使用 Nacos 的控制台去修改，配置发生变更后， Nacos 就会把最新的配置推送到该应用的所有机器上，简单而高效。</p>
<p>想想之前，为了实现此功能，写了多少冤枉代码，做了多少冤枉的运维工作。要是早一点认识 Nacos，该有多好呀！</p>
<h2>总结</h2>
<p>本文作为 Nacos 5W1H 系列文章的开篇，从“What” 讲述了 Nacos 配置管理能帮我们解决的问题：以简单、优雅、高效的方式管理配置，实现配置的动态变更，大大降低运维成本，让开发同学早点下班。</p>
<p>当然，Nacos 的配置管理，不单单只有上述的那些功能，还有诸如“灰度发布”、“版本管理”、“快速回滚”、“监听查询”、“推送轨迹”、“权限控制”、“敏感配置（如，数据库连接配置）的加密存储”等等，这些有的已经在 Nacos 中开源实现了，有的在 Nacos 配置管理的阿里云免费产品 <a href="https://cn.aliyun.com/product/acm">ACM</a> 中提供了，当然，后续也会慢慢开源到 Nacos 中，敬请期待。</p>
<p>本系列文章，会持续为大家讲述 Nacos 的点点滴滴，不单单讲述 “Nacos 能帮我们解决什么问题？”，还会深入源码分析“Nacos 是如何做到简单而强大的？”。同时，如果小伙们有兴趣的话，我们还会给大家八卦一下 Nacos 的 稗官野史，关于 Nacos 在阿里内部的历史，关于 Nacos 服务端口的寓意等等。总之，一句话：我有故事，也有美酒，君还何求？</p>
</section><footer class="footer-container" data-reactid="29"><div class="footer-body" data-reactid="30"><img src="/img/nacos_gray.png" data-reactid="31"/><div class="cols-container" data-reactid="32"><div class="col col-12" data-reactid="33"><h3 data-reactid="34">Vision</h3><p data-reactid="35">By providing an easy-to-use service infrastructure such as dynamic service discovery, service configuration, service sharing and management and etc., Nacos help users better construct, deliver and manage their own service platform, reuse and composite business service faster and deliver value of business innovation more quickly so as to win market for users in the era of cloud native and in all cloud environments, such as private, mixed, or public clouds.</p></div><div class="col col-6" data-reactid="36"><dl data-reactid="37"><dt data-reactid="38">Documentation</dt><dd data-reactid="39"><a href="/en-us/docs/what-is-nacos.html" target="_self" data-reactid="40">Overview</a></dd><dd data-reactid="41"><a href="/en-us/docs/quick-start.html" target="_self" data-reactid="42">Quick start</a></dd><dd data-reactid="43"><a href="/en-us/docs/contributing.html" target="_self" data-reactid="44">Developer guide</a></dd></dl></div><div class="col col-6" data-reactid="45"><dl data-reactid="46"><dt data-reactid="47">Resources</dt><dd data-reactid="48"><a href="/en-us/community/index.html" target="_self" data-reactid="49">Community</a></dd><dd data-reactid="50"><a href="https://www.aliyun.com/product/acm?source_type=nacos_pc_20181219" target="_self" data-reactid="51">Cloud Service ACM</a></dd><dd data-reactid="52"><a href="https://www.aliyun.com/product/edas?source_type=nacos_pc_20181219" target="_self" data-reactid="53">Cloud Service EDAS</a></dd><dd data-reactid="54"><a href="https://www.aliyun.com/product/ahas?source_type=nacos_pc_20190225" target="_self" data-reactid="55">Cloud Service AHAS</a></dd></dl></div></div><div class="copyright" data-reactid="56"><span data-reactid="57">@ 2018 The Nacos Authors | An Alibaba Middleware (Aliware) Project</span></div></div></footer></div></div>
	<script src="https://f.alicdn.com/react/15.4.1/react-with-addons.min.js"></script>
	<script src="https://f.alicdn.com/react/15.4.1/react-dom.min.js"></script>
	<script>
		window.rootPath = '';
  </script>
	<script src="/build/blogDetail.js"></script>
</body>
</html>